#include <QCoreApplication>
#include <QThread>

#include "TTaskEvent.h"
#include "TTaskQueue.h"
#include "TTaskClosure.h"
#include "TThreadPool.h"

#define XOR_MAGIC_NUM 0x23410293

TTaskQueue::TTaskQueue():m_threadPool(new TThreadPool(10))
{
    qApp->installEventFilter(this);/* 初始化必须到主线程中安装事件过滤器 */
}

TTaskQueue::~TTaskQueue()
{
}

bool TTaskQueue::eventFilter(QObject *obj, QEvent *event)
{
    (void)obj;
    if (event->type() == TTaskEvent::eventType) {
        TTaskEvent *task = dynamic_cast<TTaskEvent*>(event);
	if (!task) return false;
        if(TTaskQueue::get().g_task_closure_map.contains(task->closure)) {
            std::shared_ptr<TTaskClosureInterface> pclosure(reinterpret_cast<TTaskClosureInterface*>(task->closure));
            try {
                pclosure->invoke();
            } catch(...) {
            }

            if (task->syncSem) {
                task->syncSem->release();
            }

            /* qt执行完后会delete event */
            TTaskQueue::get().g_task_closure_map.remove(task->closure);
        }
    }

    return false;
}

bool TTaskQueue::queueGuiTask(TTask const& task,bool sync/* = false*/)
{
    if (sync && QThread::currentThread() == qApp->thread()) return false;

    // 创建任务闭包
    TTaskClosure* pclosure = new TTaskClosure(task);
    g_task_closure_map.add(pclosure);

    //Qt Event
    TTaskEvent *event = new TTaskEvent;
    event->closure = pclosure;
    event->uid = (quint64)event->closure ^ XOR_MAGIC_NUM;

    if (sync) {
        std::shared_ptr<QSemaphore> sem(new QSemaphore);
        event->syncSem = sem;
        qApp->postEvent(this,event);
        /* 这里不需要加锁，一般意义的智能指针在多线程访问，读不需要，但是读写需要，但是这是信号量，故不需要 */
        sem->acquire();
        return true;
    }

    qApp->postEvent(this,event);

    return true;
}

bool TTaskQueue::queueBackgroundTask(TTask const& task)
{
    /* 如果线程池满了，如何处理，这些任务会被一直等待吗？ */
    m_threadPool->Enqueue(task);
    return true;
}

/**
 * @brief TTaskPool::queue_timerex_task
 * @param task
 * @param delay
 * @param repeat当为重复定时器，释放由用户接管，单次定时器自动释放
 * @return 0：单次定时器或创建失败  非0：
 */
TTimer* TTaskQueue::queueTimerTask(
        TTask const& task,
        size_t delay,
        bool repeat/* = false*/
        )
{
    if (delay == 0)
        return 0;

    TTimer *timer = new TTimer(delay,repeat);

    if (!repeat) {
        timer->start(task);

        {
            std::lock_guard<std::mutex> guard(m_timerMutex);
            this->g_timer_map.push_back(timer);

            /* 每次添加新定时器将检查已过期的定时器 */
            for (TTimer *timer : g_timer_map) {
                if (timer->isExpired()) {
                    delete timer;
                    timer = nullptr;
                }
            }
        }
        return 0;
    } else {
        timer->start(task);
        return timer;
    }

    return 0;
}
